<script setup lang="ts">
import { ref, onMounted, watch, onBeforeUnmount } from 'vue'
import type { Ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton } from 'naive-ui'
import { Files, Document } from '@element-plus/icons-vue'
import { Save } from '@icon-park/vue-next'
import { ElMessage } from 'element-plus'
import type { SpaceDTO, UpdateSpaceDTO } from '@/api/DTO/space'
import type { UpdateNoteDTO } from '@/api/DTO/note'
import {
  getLoginUserSpacesServer,
  updateSpaceServer,
  addSpaceServer,
  deleteSpaceServer
} from '@/api/server/space'
import {
  updateNoteServer,
  deleteNoteServer,
  addNoteServer,
  getNoteServer
} from '@/api/server/note'
import type Node from 'element-plus/es/components/tree/src/model/node'
import editor from '@/components/editor.vue'
const route = useRoute()
const router = useRouter()
const isCollapse: Ref<boolean> = ref(false)
// 全部查出来了 需要从根空间剥离
const tree: Ref<Array<any>> = ref([])
const getTree = async () => {
  const res = await getLoginUserSpacesServer()
  tree.value = res.data
  // 1.把从后端获取的元素的属性 spaceName|title 修改为label
  // 2.把元素的noteList 加入到children
  // 3.把每个元素的id修改为key
  // 4.计算每个元素的笔记和空间数量

  const processNode = (node: any) => {
    let noteCount = node.noteList?.length || 0
    let spaceCount = 0
    // 1. 将属性 spaceName 或 title 复制 label
    node.label = node.spaceName || node.title
    node.key = node.id
    // 2. 将元素的 noteList 加入到 children 中
    if (node.noteList && node.noteList.length > 0) {
      if (!node.children) {
        node.children = []
      }
      node.noteList.forEach((note: any) => {
        node.children.unshift(note)
      })
    }
    // 3. 递归处理子节点
    if (node.children && node.children.length > 0) {
      node.children.forEach((child: any) => {
        // 递归处理子节点，并累加其返回的笔记数目和空间数目
        const { noteCount: childNoteCount, spaceCount: childSpaceCount } =
          processNode(child)
        noteCount += childNoteCount
        spaceCount += childSpaceCount
      })
      spaceCount = spaceCount + node.children.length - node.noteList.length
    }
    // 更新节点的笔记数目和空间数目属性
    node.noteCount = noteCount
    node.spaceCount = spaceCount

    // 返回当前节点的笔记数目和空间数目
    return { noteCount, spaceCount }
  }

  //4. 遍历树中的每个节点，调用递归函数处理节点
  if (!tree.value) return
  tree.value.forEach((item) => {
    processNode(item)
  })
  //5. 根据传入父空间Id重构摘取tree
  tree.value = tree.value.filter((item) => item.id === route.params.spaceId)
}
// 更新空间DTO
const updateSpaceDTO: Ref<UpdateSpaceDTO> = ref({
  spaceId: null,
  parentId: null,
  spaceName: null,
  spaceSize: null
})
//更新笔记DTO
const updateNoteDTO: Ref<UpdateNoteDTO> = ref({
  noteId: null,
  title: null,
  content: null,
  spaceId: null
})
// 拖拽节点结束的方法
const drop = async (draggingNode: Node, dropNode: Node) => {
  const dragNode = draggingNode.data
  const targetNode = dropNode.data
  if (targetNode?.type === 'space') {
    // 拖拽空间
    if (dragNode?.type === 'space') {
      updateSpaceDTO.value.spaceId = dragNode.id
      updateSpaceDTO.value.parentId = targetNode.id
      await updateSpaceServer(updateSpaceDTO.value)
      updateSpaceDTO.value = {
        spaceId: null,
        parentId: null,
        spaceName: null,
        spaceSize: null
      }
      // 拖拽笔记
    } else if (dragNode?.type === 'note') {
      updateNoteDTO.value.noteId = dragNode.id
      updateNoteDTO.value.spaceId = targetNode.id
      await updateNoteServer(updateNoteDTO.value)
      updateNoteDTO.value = {
        noteId: null,
        title: null,
        content: null,
        spaceId: null
      }
    }
  } else {
    ElMessage.info('暂未排序')
  }
  await getTree()
}
// 收缩/伸展分割线
const splitSize: Ref<any> = ref(0.15)
const handleCollapse = () => {
  splitSize.value = 0.01
}
const handleExpand = () => {
  splitSize.value = 0.15
}
// 新增子空间
const spaceDTO: Ref<SpaceDTO> = ref({
  spaceName: null,
  spaceDesc: null,
  parentId: route.params.spaceId
})
const showPopover: Ref<boolean> = ref(false)
const showAddSpace: Ref<boolean> = ref(false)
const addSpace = async () => {
  showAddSpace.value = !showAddSpace.value
}

const toggleShowPopover = () => {
  showPopover.value = !showPopover.value
}

const addSpaceEnter = async () => {
  if (
    spaceDTO.value.spaceName.trim() === '' ||
    spaceDTO.value.spaceName === null
  ) {
    return ElMessage.warning('请输入空间名')
  }
  showPopover.value = !showPopover.value
  const res = await addSpaceServer(spaceDTO.value)
  await getTree()
}

const showAddNote: Ref<boolean> = ref(false)
// 新增笔记
const addNote: Ref<any> = ref({
  title: null,
  content: null,
  spaceId: null
})
const addNoteEnter = async () => {
  if (addNote.value.title.trim() === '' || addNote.value.title === null) {
    return ElMessage.warning('请输入笔记标题')
  }
  if (addNote.value.title.length > 45) {
    return ElMessage.warning('笔记标题过长')
  }
  addNote.value.spaceId = route.params.spaceId
  await addNoteServer(addNote.value)
  showPopover.value = !showPopover.value
  await getTree()
}
//删除空间/笔记
const showDeleteDialog: Ref<any> = ref(false)
const deleteData: Ref<any> = ref()
const openDeleteDialog = (data: any) => {
  deleteData.value = data
  showDeleteDialog.value = !showDeleteDialog.value
}
const handleDelete = async () => {
  const spaceId = deleteData.value?.id
  const noteId = deleteData.value?.id
  // 删除空间，有孩子则不能删除
  if (deleteData.value?.children) {
    ElMessage.error('有孩子不能删除')
  } else if (deleteData.value?.type === 'space') {
    const res = await deleteSpaceServer(spaceId)
  } else if (deleteData.value?.type == 'note') {
    const res = await deleteNoteServer(noteId)
  }
  showDeleteDialog.value = !showDeleteDialog.value
  await getTree()
}
// 点击节点获取空间/笔记 -> 跳转路由
const getNodeData = async (node: any) => {
  if (node.type === 'note') {
    const noteId = node.id
    router.push({
      name: 'content',
      query: {
        noteId: node.id
      }
    })
  }
  if (node.type === 'space') {
    const spaceId = node.id
    //额外携带数量参数
    router.push({
      name: 'content',
      query: {
        spaceId: spaceId,
        spaceCount: node.spaceCount,
        noteCount: node.noteCount
      }
    })
  }
}
//监听shoPopover重置选项
watch(
  showPopover,
  (newVal) => {
    if (!newVal) {
      spaceDTO.value.spaceName = ''
      spaceDTO.value.parentId = route.params.spaceId
      showAddSpace.value = false
      addNote.value = {
        title: null,
        content: null,
        spaceId: null
      }
      showAddNote.value = false
    }
  },
  {
    immediate: true
  }
)

onMounted(async () => {
  await getTree()
})
</script>

<template>
  <div class="space-page">
    <n-layout has-sider class="sider-layout">
      <n-split
        direction="horizontal"
        :min="0.15"
        :max="0.3"
        class="main-split"
        v-model:size="splitSize"
      >
        <template #1>
          <n-layout-sider
            :bordered="true"
            collapse-mode="width"
            :collapsed-width="0"
            width="100%"
            show-trigger="arrow-circle"
            :native-scrollbar="false"
            :on-after-leave="handleCollapse"
            :on-after-enter="handleExpand"
          >
            <n-split
              direction="vertical"
              class="sider"
              :default-size="0.15"
              :min="0.1"
              :max="0.25"
            >
              <template #1>
                <div class="sider-top">
                  <n-flex justify="space-around">
                    <n-flex justify="center">
                      <el-icon size="25px" @click="router.back()"
                        ><ArrowLeft
                      /></el-icon>
                      <div
                        class="space-name"
                        style="height: 14px; font-size: 14px"
                      >
                        <el-icon size="14px"><Files /></el-icon>
                        {{ route.params.spaceName }}
                      </div>
                    </n-flex>
                    <n-popover
                      trigger="manual"
                      placement="bottom-start"
                      :show="showPopover"
                    >
                      <template #trigger>
                        <n-button
                          type="primary"
                          round
                          @click="toggleShowPopover"
                        >
                          <el-icon size="14px" v-if="!showPopover"
                            ><Plus
                          /></el-icon>
                          <el-icon v-else><Close /></el-icon>
                        </n-button>
                      </template>

                      <template #default>
                        <n-flex vertical>
                          <!-- 新建笔记 -->
                          <n-button
                            v-if="!showAddNote"
                            @click="showAddNote = !showAddNote"
                            >新建笔记</n-button
                          >
                          <n-flex vertical v-else-if="showAddNote">
                            <n-input
                              type="textarea"
                              placeholder="新笔记名 "
                              v-model:value="addNote.title"
                              autofocus
                              round
                              @keyup.enter="addNoteEnter"
                            />
                            <n-button @click="addNoteEnter" round
                              >创建笔记</n-button
                            >
                            <el-divider border-style="double" />
                          </n-flex>
                          <n-button @click="addSpace" v-show="!showAddSpace"
                            >新建子空间</n-button
                          >
                          <n-flex vertical v-show="showAddSpace">
                            <el-divider border-style="double" />
                            <n-input
                              placeholder="新空间名 "
                              v-model:value="spaceDTO.spaceName"
                              autofocus
                              round
                              @keyup.enter="addSpaceEnter"
                            />
                            <n-input
                              type="textarea"
                              placeholder="新空间描述"
                              v-model:value="spaceDTO.spaceDesc"
                              round
                              @keyup.enter="addSpaceEnter"
                            />
                            <n-button @click="addSpaceEnter" round
                              >创建空间</n-button
                            >
                          </n-flex>
                        </n-flex>
                      </template>
                    </n-popover>
                  </n-flex>
                </div>
              </template>
              <template #2>
                <n-flex justify="space-between" style="margin: 10px 10px">
                  <n-button text
                    ><n-flex justify="space-between">
                      <el-icon size="14px"><List /></el-icon>
                      <span style="font-size: 14px">目录</span>
                    </n-flex></n-button
                  >
                  <n-button
                    text
                    style="margin-right: 10px"
                    v-if="isCollapse"
                    @click="isCollapse = !isCollapse"
                    ><el-icon><Expand /></el-icon>展开</n-button
                  >
                  <n-button
                    text
                    style="margin-right: 10px"
                    v-else
                    @click="isCollapse = !isCollapse"
                    ><el-icon><Fold /></el-icon>收起</n-button
                  >
                </n-flex>
                <el-tree
                  :data="tree"
                  node-key="id"
                  default-expand-all
                  :expand-on-click-node="false"
                  draggable
                  @node-click="getNodeData"
                  @node-drop="drop"
                >
                  <template #default="{ data }">
                    <n-flex justify="space-between" style="width: 100%">
                      <el-icon v-if="data.type === 'space'"><Folder /></el-icon>
                      <el-icon v-else><Document /></el-icon>
                      <span>{{ data.label }}</span>
                      <n-button
                        size="tiny"
                        @click="openDeleteDialog(data)"
                        v-if="data.id != route.params.spaceId"
                        >删除</n-button
                      >

                      <n-badge
                        v-else
                        :value="tree[0].noteCount"
                        :max="15"
                        color="#66ccff"
                        type="success"
                      />
                    </n-flex>
                  </template>
                </el-tree>
              </template>
            </n-split> </n-layout-sider
        ></template>
        <template #2>
          <div class="content" style="margin-left: 5px">
            <router-view></router-view>
          </div>
        </template>
      </n-split>
    </n-layout>
    <!-- 需要弹出的对话框们 -->
    <!-- 删除确认框 -->
    <n-modal
      ref="deleteDialog"
      v-model:show="showDeleteDialog"
      preset="dialog"
      title="Dialog"
    >
      <template #header>
        <div>删除空间|笔记</div>
      </template>
      <div>确认删除空间|笔记?</div>
      <template #action>
        <div>
          <n-button @click="showDeleteDialog = !showDeleteDialog"
            >取消</n-button
          >
          <n-button @click="handleDelete">确认</n-button>
        </div>
      </template>
    </n-modal>
  </div>
</template>

<style scoped lang="scss">
.space-page {
  margin: 0;
  height: 100%;
  $head-height: 60px;
  $footer-height: 50px;
  $main-height: calc(100vh - $head-height - $footer-height);
  .el-tree-node__content {
    height: 100px;
  }
  .n-layout {
    .n-split {
      height: $main-height;
      .n-layout-sider {
        height: 100%;
        .n-split {
          .sider-top {
            margin-top: 20px;
            display: flex;
            //垂直居中
            align-items: center;
            justify-content: center;
          }
        }
      }
    }
  }
  .note-content {
    height: $main-height;
    .el-card {
      min-height: 100%;
    }
  }
  .space-content {
    height: $main-height;
    .el-card {
      min-height: 100%;
    }
  }
}
</style>
